{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "wFPyjGqMQ82Q"
      },
      "source": [
        "##### Copyright 2020 The TensorFlow Authors.\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "cellView": "form",
        "id": "aNZ7aEDyQIYU"
      },
      "outputs": [],
      "source": [
        "#@title Licensed under the Apache License, Version 2.0 (the \"License\");\n",
        "# you may not use this file except in compliance with the License.\n",
        "# You may obtain a copy of the License at\n",
        "#\n",
        "# https://www.apache.org/licenses/LICENSE-2.0\n",
        "#\n",
        "# Unless required by applicable law or agreed to in writing, software\n",
        "# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
        "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
        "# See the License for the specific language governing permissions and\n",
        "# limitations under the License."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "uMOmzhPEQh7b"
      },
      "source": [
        "# 정규화\n",
        "\n",
        "<table class=\"tfo-notebook-buttons\" align=\"left\">\n",
        "  <td><a target=\"_blank\" href=\"https://www.tensorflow.org/addons/tutorials/layers_normalizations\"><img src=\"https://www.tensorflow.org/images/tf_logo_32px.png\">TensorFlow.org에서 보기</a></td>\n",
        "  <td><a target=\"_blank\" href=\"https://colab.research.google.com/github/tensorflow/docs-l10n/blob/master/site/ko/addons/tutorials/layers_normalizations.ipynb\"><img src=\"https://www.tensorflow.org/images/colab_logo_32px.png\">Google Colab에서 실행하기</a></td>\n",
        "  <td><a target=\"_blank\" href=\"https://github.com/tensorflow/docs-l10n/blob/master/site/ko/addons/tutorials/layers_normalizations.ipynb\"><img src=\"https://www.tensorflow.org/images/GitHub-Mark-32px.png\">GitHub에서 소스 보기</a></td>\n",
        "  <td><a href=\"https://storage.googleapis.com/tensorflow_docs/docs-l10n/site/ko/addons/tutorials/layers_normalizations.ipynb\"><img src=\"https://www.tensorflow.org/images/download_logo_32px.png\">노트북 다운로드하기</a></td>\n",
        "</table>\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "cthm5dovQMJl"
      },
      "source": [
        "## 개요\n",
        "\n",
        "이 노트북은 TensorFlow의 [정규화 레이어](https://github.com/tensorflow/addons/blob/master/tensorflow_addons/layers/normalizations.py)에 대한 간략한 소개를 제공합니다. 현재 지원되는 레이어는 다음과 같습니다.\n",
        "\n",
        "- **그룹 정규화**(TensorFlow Addons)\n",
        "- **인스턴스 정규화**(TensorFlow Addons)\n",
        "- **레이어 정규화**(TensorFlow Core)\n",
        "\n",
        "레이어의 기본 아이디어는 활성 레이어의 출력을 정규화하여 훈련 중 수렴을 개선하는 것입니다. [배치 정규화](https://keras.io/layers/normalization/)와 달리, 이러한 정규화는 배치에서 동작하지 않고 대신 단일 샘플의 활성화를 정규화하여 순환 신경망에도 적합합니다.\n",
        "\n",
        "일반적으로 정규화는 입력 텐서에서 하위 그룹의 평균과 표준 편차를 계산하여 수행됩니다. 여기에 스케일과 오프셋 인자를 적용하는 것도 가능합니다.\n",
        "\n",
        "$y_{i} = \\frac{\\gamma ( x_{i} - \\mu )}{\\sigma }+ \\beta$\n",
        "\n",
        "$ y$ : 출력\n",
        "\n",
        "$x$ : 입력\n",
        "\n",
        "$\\gamma$ : 스케일 인자\n",
        "\n",
        "$\\mu$: 평균\n",
        "\n",
        "$\\sigma$: 표준 편차\n",
        "\n",
        "$\\beta$: 오프셋 인자\n",
        "\n",
        "다음 이미지는 기술 간의 차이점을 보여줍니다. 각 하위 플롯은 N이 배치 축, C가 채널 축, (H, W)가 공간 축(예: 그림의 높이 및 너비)인 입력 텐서를 보여줍니다. 파란색 픽셀은 이들 픽셀의 값을 집계하여 계산된, 동일한 평균 및 분산으로 정규화됩니다.\n",
        "\n",
        "![](https://github.com/shaohua0116/Group-Normalization-Tensorflow/raw/master/figure/gn.png)\n",
        "\n",
        "출처: (https://arxiv.org/pdf/1803.08494.pdf)\n",
        "\n",
        "가중치 감마 및 베타는 모든 정규화 레이어에서 훈련 가능하며 표현 능력의 손실 가능성을 보상합니다. `center` 또는 `scale` 플래그를 `True`로 설정하여 이들 요소를 활성화할 수 있습니다. 물론 `beta` 및 `gamma`에 `initializers`, `constraints` 및 `regularizer`를 사용하여 훈련 프로세스 중에 이들 값을 조정할 수 있습니다. "
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "I2XlcXf5WBHb"
      },
      "source": [
        "## 설정"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "kTlbneoEUKrD"
      },
      "source": [
        "### Tensorflow 2.0 및 Tensorflow-Addons 설치"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "_ZQGY_ALnirQ"
      },
      "outputs": [],
      "source": [
        "!pip install -U tensorflow-addons"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "7aGgPZG_WBHg"
      },
      "outputs": [],
      "source": [
        "import tensorflow as tf\n",
        "import tensorflow_addons as tfa"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "u82Gz_gOUPDZ"
      },
      "source": [
        "### 데이터세트 준비하기"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "3wso9oidUZZQ"
      },
      "outputs": [],
      "source": [
        "mnist = tf.keras.datasets.mnist\n",
        "\n",
        "(x_train, y_train),(x_test, y_test) = mnist.load_data()\n",
        "x_train, x_test = x_train / 255.0, x_test / 255.0"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "UTQH56j89POZ"
      },
      "source": [
        "## 그룹 정규화 튜토리얼\n",
        "\n",
        "### 소개\n",
        "\n",
        "그룹 정규화(GN)는 입력 채널을 더 작은 하위 그룹으로 나누고 평균과 분산을 기반으로 값을 정규화합니다. GN은 단일 예제에서 동작하므로 이 기술은 배치 크기와 독립적입니다.\n",
        "\n",
        "GN은 실험적으로 이미지 분류 작업에서 배치 정규화와 비슷한 점수를 기록했습니다. 전체 batch_size가 낮은 경우 이때 배치 정규화의 성능이 저하될 수 있으며, 배치 정규화 대신 GN을 사용하는 것이 유용할 수 있습니다.\n",
        "\n",
        "###표준 \"channels last\" 설정에서 Conv2D 레이어 이후 10개의 채널을 5개의 하위 그룹으로 분할하는 예제"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "aIGjLwYWAm0v"
      },
      "outputs": [],
      "source": [
        "model = tf.keras.models.Sequential([\n",
        "  # Reshape into \"channels last\" setup.\n",
        "  tf.keras.layers.Reshape((28,28,1), input_shape=(28,28)),\n",
        "  tf.keras.layers.Conv2D(filters=10, kernel_size=(3,3),data_format=\"channels_last\"),\n",
        "  # Groupnorm Layer\n",
        "  tfa.layers.GroupNormalization(groups=5, axis=3),\n",
        "  tf.keras.layers.Flatten(),\n",
        "  tf.keras.layers.Dense(128, activation='relu'),\n",
        "  tf.keras.layers.Dropout(0.2),\n",
        "  tf.keras.layers.Dense(10, activation='softmax')\n",
        "])\n",
        "\n",
        "model.compile(optimizer='adam',\n",
        "              loss='sparse_categorical_crossentropy',\n",
        "              metrics=['accuracy'])\n",
        "model.fit(x_test, y_test)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "QMwUfJUib3ka"
      },
      "source": [
        "## 인스턴스 정규화 튜토리얼\n",
        "\n",
        "### 소개\n",
        "\n",
        "인스턴스 정규화는 그룹 크기가 채널 크기(또는 축 크기)와 같은 그룹 정규화의 특수한 경우입니다.\n",
        "\n",
        "실험 결과는 배치 정규화를 대체할 때 인스턴스 정규화가 스타일 전송에서 잘 수행됨을 보여줍니다. 최근에는 인스턴스 정규화가 GAN에서 배치 정규화를 대체하는 용도로도 사용되었습니다.\n",
        "\n",
        "### 예제\n",
        "\n",
        "Conv2D 레이어 다음에 InstanceNormalization을 적용하고 균일하게 초기화된 스케일 및 오프셋 인자를 사용합니다."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "6sLVv-C8f6Kf"
      },
      "outputs": [],
      "source": [
        "model = tf.keras.models.Sequential([\n",
        "  # Reshape into \"channels last\" setup.\n",
        "  tf.keras.layers.Reshape((28,28,1), input_shape=(28,28)),\n",
        "  tf.keras.layers.Conv2D(filters=10, kernel_size=(3,3),data_format=\"channels_last\"),\n",
        "  # LayerNorm Layer\n",
        "  tfa.layers.InstanceNormalization(axis=3, \n",
        "                                   center=True, \n",
        "                                   scale=True,\n",
        "                                   beta_initializer=\"random_uniform\",\n",
        "                                   gamma_initializer=\"random_uniform\"),\n",
        "  tf.keras.layers.Flatten(),\n",
        "  tf.keras.layers.Dense(128, activation='relu'),\n",
        "  tf.keras.layers.Dropout(0.2),\n",
        "  tf.keras.layers.Dense(10, activation='softmax')\n",
        "])\n",
        "\n",
        "model.compile(optimizer='adam',\n",
        "              loss='sparse_categorical_crossentropy',\n",
        "              metrics=['accuracy'])\n",
        "model.fit(x_test, y_test)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "qYdnEocRUCll"
      },
      "source": [
        "## 레이어 정규화 튜토리얼\n",
        "\n",
        "### 소개\n",
        "\n",
        "레이어 정규화는 그룹 크기가 1인 그룹 정규화의 특수한 경우입니다. 평균과 표준 편차는 단일 샘플의 모든 활성화에서 계산됩니다.\n",
        "\n",
        "실험 결과는 레이어 정규화가 배치 크기와는 독립적으로 동작하기 때문에 순환 신경망에 적합하다는 것을 보여줍니다.\n",
        "\n",
        "### 예제\n",
        "\n",
        "Conv2D 레이어 다음에 레이어 정규화를 적용하고 스케일 및 오프셋 인자를 사용합니다. "
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "Fh-Pp_e5UB54"
      },
      "outputs": [],
      "source": [
        "model = tf.keras.models.Sequential([\n",
        "  # Reshape into \"channels last\" setup.\n",
        "  tf.keras.layers.Reshape((28,28,1), input_shape=(28,28)),\n",
        "  tf.keras.layers.Conv2D(filters=10, kernel_size=(3,3),data_format=\"channels_last\"),\n",
        "  # LayerNorm Layer\n",
        "  tf.keras.layers.LayerNormalization(axis=1 , center=True , scale=True),\n",
        "  tf.keras.layers.Flatten(),\n",
        "  tf.keras.layers.Dense(128, activation='relu'),\n",
        "  tf.keras.layers.Dropout(0.2),\n",
        "  tf.keras.layers.Dense(10, activation='softmax')\n",
        "])\n",
        "\n",
        "model.compile(optimizer='adam',\n",
        "              loss='sparse_categorical_crossentropy',\n",
        "              metrics=['accuracy'])\n",
        "model.fit(x_test, y_test)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "shvGfnB0WpQQ"
      },
      "source": [
        "## 문헌\n",
        "\n",
        "[Layer norm](https://arxiv.org/pdf/1607.06450.pdf)\n",
        "\n",
        "[Instance norm](https://arxiv.org/pdf/1607.08022.pdf)\n",
        "\n",
        "[Group Norm](https://arxiv.org/pdf/1803.08494.pdf)\n",
        "\n",
        "[Complete Normalizations Overview](http://mlexplained.com/2018/11/30/an-overview-of-normalization-methods-in-deep-learning/)"
      ]
    }
  ],
  "metadata": {
    "colab": {
      "collapsed_sections": [],
      "name": "layers_normalizations.ipynb",
      "toc_visible": true
    },
    "kernelspec": {
      "display_name": "Python 3",
      "name": "python3"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}
